package com.iteaj.iot.plc.siemens;

import com.iteaj.iot.plc.PlcAddressResolver;
import com.iteaj.iot.plc.PlcException;
import com.iteaj.iot.plc.PlcProtocolType;

import java.util.Locale;

/**
 * 西门子地址解析器
 */
public class SiemensAddressResolver extends PlcAddressResolver {
    /**
     * 获取等待读取的数据的代码
     * @return code
     */
    public int getDataCode() {
        return DataCode;
    }

    /**
     * 设置等待读取的数据的代码
     * @param dataCode 数据代码
     */
    public void setDataCode(int dataCode) {
        DataCode = dataCode;
    }

    private int DataCode = 0;

    /**
     * 获取PLC的DB块数据信息
     * @return int
     */
    public int getDbBlock() {
        return DbBlock;
    }

    /**
     * 设置PLC的DB块数据信息
     * @param dbBlock value
     */
    public void setDbBlock(int dbBlock) {
        DbBlock = dbBlock;
    }

    private int DbBlock = 0;

    /**
     * 转换到位操作合适的地址信息
     */
    public void convertToBoolean() {
        int addressStart = this.getAddressStart();
        int offset = addressStart % 8;
        this.setAddressStart(addressStart - offset) ;

//        result.Content3 = offset;
    }

    /**
     * 计算特殊地址信息
     * @param address 字符串地址
     * @param isCT 是否是定时器和计数器的地址
     * @return 实际值
     */
    public static int calcAddressStarted(String address, boolean isCT) {
        if (address.indexOf( '.' ) < 0) {
            if (isCT)
                return Integer.parseInt( address );
            else
                return Integer.parseInt( address ) * 8;
        }else {
            String[] temp = address.split( "\\." );
            return Integer.parseInt( temp[0] ) * 8 + Integer.parseInt( temp[1] );
        }
    }

    /**
     * 地址里面解析出地址对象
     * @param address 地址数据信息
     * @return 地址元对象
     */
    public static SiemensAddressResolver ParseFrom( String address)
    {
        return ParseFrom( address, 0 );
    }

    /**
     * 从实际的西门子的地址里面解析出地址对象
     * @param address 地址数据信息
     * @param length 读取的数据长度
     * @return 地址元对象
     */
    public static SiemensAddressResolver ParseFrom(String address, int length) {
        SiemensAddressResolver addressData = new SiemensAddressResolver();
        try {
            addressData.setLength(length);
            addressData.DbBlock = 0;
            String tempAddress = address.toUpperCase(Locale.ROOT);
            if (tempAddress.startsWith( "AI" )){
                addressData.DataCode = (byte) 0x06;
                if (tempAddress.startsWith( "AIX" ) || tempAddress.startsWith( "AIB" )
                        || tempAddress.startsWith( "AIW" ) || tempAddress.startsWith( "AID" ))
                    addressData.setAddressStart( calcAddressStarted( address.substring( 3 ), false ));
                else
                    addressData.setAddressStart( calcAddressStarted( address.substring( 2 ), false ));
            } else if (tempAddress.startsWith( "AQ" )){
                addressData.DataCode = (byte) 0x07;
                if (tempAddress.startsWith( "AQX" ) || tempAddress.startsWith( "AQB" )
                        || tempAddress.startsWith( "AQW" ) || tempAddress.startsWith( "AQD" ))
                    addressData.setAddressStart( calcAddressStarted( address.substring( 3 ) , false) );
                else
                    addressData.setAddressStart( calcAddressStarted( address.substring( 2 ) , false) );
            } else if (tempAddress.charAt(0) == 'I') {
                addressData.DataCode = 0x81;
                if (tempAddress.startsWith( "IX" ) || tempAddress.startsWith( "IB" )
                        || tempAddress.startsWith( "IW" ) || tempAddress.startsWith( "ID" ))
                    addressData.setAddressStart(calcAddressStarted(address.substring(2), false));
                else
                    addressData.setAddressStart(calcAddressStarted(address.substring(1), false));
            } else if (tempAddress.charAt(0) == 'Q') {
                addressData.DataCode = 0x82;
                if (tempAddress.startsWith( "QX" ) || tempAddress.startsWith( "QB" )
                        || tempAddress.startsWith( "QW" ) || tempAddress.startsWith( "QD" ))
                    addressData.setAddressStart(calcAddressStarted(address.substring(2), false));
                else
                    addressData.setAddressStart(calcAddressStarted(address.substring(1), false));
            } else if (tempAddress.charAt(0) == 'M') {
                addressData.DataCode = 0x83;
                if (tempAddress.startsWith( "MX" ) || tempAddress.startsWith( "MB" )
                        || tempAddress.startsWith( "MW" ) || tempAddress.startsWith( "MD" ))
                    addressData.setAddressStart(calcAddressStarted(address.substring(2), false));
                else
                    addressData.setAddressStart(calcAddressStarted(address.substring(1), false));
            } else if (tempAddress.charAt(0) == 'D' || tempAddress.startsWith("DB")) {
                addressData.DataCode = 0x84;
                String[] adds = tempAddress.split("\\.");
                if (tempAddress.charAt(1) == 'B') {
                    addressData.DbBlock = Integer.parseInt(adds[0].substring(2));
                } else {
                    addressData.DbBlock = Integer.parseInt(adds[0].substring(1));
                }
                String addTemp = tempAddress.substring( tempAddress.indexOf( '.' ) + 1 );
                if (addTemp.startsWith( "DBX" ) || addTemp.startsWith( "DBB" )
                        || addTemp.startsWith( "DBW" ) || addTemp.startsWith( "DBD" ))
                    addTemp = addTemp.substring( 3 );
                addressData.setAddressStart(calcAddressStarted(addTemp, false));
            } else if (tempAddress.charAt(0) == 'T') {
                addressData.DataCode = 0x1F;
                addressData.setAddressStart(calcAddressStarted(address.substring(1), true));
            } else if (tempAddress.charAt(0) == 'C') {
                addressData.DataCode = 0x1E;
                addressData.setAddressStart(calcAddressStarted(address.substring(1), true));
            } else if (tempAddress.charAt(0) == 'V') {
                addressData.DataCode = 0x84;
                addressData.DbBlock = 1;
                if (tempAddress.startsWith( "VB" ) || tempAddress.startsWith( "VW" )
                        || tempAddress.startsWith( "VD" ) || tempAddress.startsWith( "VX" )){
                    addressData.setAddressStart(calcAddressStarted(address.substring(2), false));
                }
                else {
                    addressData.setAddressStart(calcAddressStarted(address.substring(1), false));
                }
            } else {
                throw new PlcException("S7不支持的地址["+address+"]", PlcProtocolType.SiemensS7);
            }
        } catch (Exception ex) {
            throw new PlcException(ex.getMessage(), ex, PlcProtocolType.SiemensS7);
        }

        return addressData;
    }
}
